package com.kara.woodAgent.agent.graph.communicate;


import com.kara.woodAgent.agent.graph.impl.ResumePayload;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author tzy
 * @version 1.0
 * @project wood_agent
 * @description
 * @date 2025/6/4 15:21:04
 */
public class Channel {

	private  ConcurrentHashMap<String, List<Function<ChannelPayload, ChannelMessage>>> eventListeners = new ConcurrentHashMap<>();

	private Function<ChannelPayload, ChannelMessage> userInputListener;

	private Function<ChannelPayload, ChannelMessage> checkpointListener;

	private Supplier<Boolean> statusListener;

	public ChannelMessage waitInput(ChannelPayload payload) {
		return userInputListener.apply(payload);
	}

	public boolean checking() {
		return statusListener.get();
	}


	public void checkpoint(ChannelPayload payload) {
		if (payload == null) {
			throw new RuntimeException("checkpoint payload can not be null");
		}

		if (payload instanceof ResumePayload) {
			throw new RuntimeException("checkpoint payload can not be ResumePayload");
		}
		checkpointListener.apply(payload);
	}

	public ChannelMessage resume() {
		return checkpointListener.apply(ResumePayload.of());
	}


	public void addEventListener(String event, Function<ChannelPayload, ChannelMessage> listener) {
		List<Function<ChannelPayload, ChannelMessage>> functions = eventListeners.computeIfAbsent(event, k -> new CopyOnWriteArrayList<>());
		functions.add(listener);
	}


	public void addWaitUserInputEventListener(Function<ChannelPayload, ChannelMessage> listener) {
		this.userInputListener = listener;
	}

	public void addCheckpointListener(Function<ChannelPayload, ChannelMessage> listener) {
		this.checkpointListener = listener;
	}

	public void addStatusListener(Supplier<Boolean> listener) {
		this.statusListener = listener;
	}

	public List<ChannelMessage> publish(String event, ChannelPayload payload) {
		return eventListeners.get(event).stream()
				.map(listener -> listener.apply(payload)).toList();
	}

	public Channel copy() {
		Channel channel = new Channel();
		channel.eventListeners = eventListeners;
//		channel.addWaitUserInputEventListener(this.userInputListener);
//		channel.addCheckpointListener(this.checkpointListener);
//		channel.addStatusListener(this.statusListener);
		return channel;
	}
}
